/*
 * @Author: wangshuixin 2412658453@qq.com
 * @Date: 2024-06-16 15:13:48
 * @LastEditors: wangshuixin 2412658453@qq.com
 * @LastEditTime: 2024-12-27 09:08:58
 * @FilePath: /tspods/utils/number.ts
 * @Description: 数字
 */
import type { ExpressionTerm, FractionTerm, VariableTermElement } from '@/types/equation'
import { mathematics_addition } from './mathematics';

/**
 * @function 生成0到1之间的随机数
*/
export const createRandomNumbers = () => {
  return Math.random();
}

/**
 * @function 格式化常数
 * @param {ExpressionTerm} data 待格式化的数据
*/
export const formatConstant = (data: ExpressionTerm) => {
  const constant = safeDeepCopy(data.constant)
  let isTop = true
  let top: VariableTermElement[] = []
  let bottom: VariableTermElement[] = []
  // 格式化数据
  let formattedData: FractionTerm[] = []
  // 整个分数的符号
  let fractionType: any = undefined
  if (constant) {
    constant.forEach((item: VariableTermElement) => {
      if (item.text === '/') {
        // '/'代表分母的结尾
        isTop = true
      }
      else if (item.text === '\n') {
        // '\n'代表分子的结尾和分母的开头
        isTop = false
      }
      if (isTop && item.text !== '' && item.text !== '/') {
        top.push(item)
      } else if (!isTop && item.text !== '\n') {
        bottom.push(item)
      }
      if (item.text === '' || item.text === '/') {
        // 添加分数及分数之前的数据
        formattedData.push({
          top: JSON.parse(JSON.stringify(top)),
          bottom: JSON.parse(JSON.stringify(bottom)),
          type: fractionType ? JSON.parse(JSON.stringify(fractionType)) : undefined
        })
        // 重置 分子、分母 存储器
        top = []
        bottom = []
        // 空字符''代表分数分子的开头
        fractionType = item.type
      }
    })
    // 添加分数之后数据
    formattedData.push({ 
      top,
      bottom,
      type: fractionType
    })
  }
  return formattedData
}

/**
 * @function 求和
 * @param {string} previous 前一个加数因子
 * @param {string} next 后一个加数因子
*/
export const constant_addition = (previous: string, next: string): string => {
  // 拆分分子与分母
  const previousFactor_top = getFractionTopOrBottom(previous, 'top', false)
  const previousFactor_bottom = getFractionTopOrBottom(previous, 'bottom', false)
  const nextFactor_top = getFractionTopOrBottom(next, 'top', false)
  const nextFactor_bottom = getFractionTopOrBottom(next, 'bottom', false)
  // 计算需要兼容 字母参数 stringContainChars
  const bottom = integerMultiply(previousFactor_bottom, nextFactor_bottom)
  const top = integerAddition(integerMultiply(previousFactor_top, nextFactor_bottom), integerMultiply(nextFactor_top, previousFactor_bottom))  
  console.log(top, "底部》", bottom);
  
  // 获取分子与分母的最大公因数
  const commonFactor = getHighestCommonFactor(top, bottom)
  console.log("最大公因数", commonFactor); // 9
  
  // 化简分子与分母
  const num_top = reduceFraction(top, commonFactor)
  const num_bottom = reduceFraction(bottom, commonFactor)
  const result = num_bottom !== '1' ? `${num_top}/${num_bottom}` : `${num_top}`

  return result
}

/**
 * @function 进行运算
 * @param {ExpressionTerm[]} expressionTerms 表达式数据
*/
export const calculateExpression = (expressionTerms: ExpressionTerm[]) => {
  let newExpressionTerms = [] as ExpressionTerm[]
  // 暂时不考虑括号的情况，同时先计算整数且不含字母，默认没有未知数
  let text = 0
  let constantVariable = {
    constant: [
      {
        text: '0'
      }
    ]
  } as ExpressionTerm
  expressionTerms.forEach( (term: ExpressionTerm) => {
    // console.log("项目》", term)
    constantVariable = mathematics_addition(constantVariable, term)
    console.log("每步运算的结果》", constantVariable)

    // if (term.constant && term.constant[0].text === '=') {
    //   return
    // } else {
    //   constantVariable = mathematics_addition(constantVariable, term)
    //   console.log("项目》", constantVariable)

    //   if (!term.type) {
    //     text += Number(term.constant![0].text)
    //   } else if (term.type === '1') {
    //     text += Number(term.constant![0].text)
    //   } else if (term.type === '2') {
    //     text -= Number(term.constant![0].text)
    //   } else if (term.type === '3') {
    //     text = text * Number(term.constant![0].text)
    //   } else if (term.type === '4') {
    //     text = text / Number(term.constant![0].text)
    //   }
    // }
  })
  console.log("答案》", constantVariable);
  newExpressionTerms = [constantVariable]
  // console.log("运算", expressionTerms);
  return newExpressionTerms
}


/**
 * @function 获取分数的倒数
 * @param {string} fractionString 待置换的数值的字符串
*/
export const invertFractionTopAndBottom = (fractionString: string) => {
  const top = getFractionTopOrBottom(fractionString, 'top', false)
  const bottom = getFractionTopOrBottom(fractionString, 'bottom', false)
  const newFractionString = top !== '1' ? `${bottom}/${top}` : `${bottom}`
  return newFractionString
}

/**
 * @function 求和 - 计算因子相加
 * @param {string} previousFactor 前一个加数因子
 * @param {string} nextFactor 后一个加数因子
*/
export const calculateFactor_addition = (previousFactor: string, nextFactor: string): string => {
  // 拆分分子与分母
  const previousFactor_top = getFractionTopOrBottom(previousFactor, 'top', false)
  const previousFactor_bottom = getFractionTopOrBottom(previousFactor, 'bottom', false)
  const nextFactor_top = getFractionTopOrBottom(nextFactor, 'top', false)
  const nextFactor_bottom = getFractionTopOrBottom(nextFactor, 'bottom', false)
  // 计算需要兼容 字母参数 stringContainChars
  const bottom = integerMultiply(previousFactor_bottom, nextFactor_bottom)
  const top = integerAddition(integerMultiply(previousFactor_top, nextFactor_bottom), integerMultiply(nextFactor_top, previousFactor_bottom))  
  console.log(top, "底部》", bottom);
  
  // 获取分子与分母的最大公因数
  const commonFactor = getHighestCommonFactor(top, bottom)
  console.log("最大公因数", commonFactor); // 9
  
  // 化简分子与分母
  const num_top = reduceFraction(top, commonFactor)
  const num_bottom = reduceFraction(bottom, commonFactor)
  const result = num_bottom !== '1' ? `${num_top}/${num_bottom}` : `${num_top}`

  return result
}

/**
 * @function 求差 - 计算因子相减
 * @param {string} previousFactor 被减数因子
 * @param {string} nextFactor 减数因子
*/
export const calculateFactor_subtraction = (previousFactor: string, nextFactor: string): string => {
  // 拆分分子与分母
  const previousFactor_top = getFractionTopOrBottom(previousFactor, 'top', false)
  const previousFactor_bottom = getFractionTopOrBottom(previousFactor, 'bottom', false)
  const nextFactor_top = getFractionTopOrBottom(nextFactor, 'top', false)
  const nextFactor_bottom = getFractionTopOrBottom(nextFactor, 'bottom', false)
  // 计算需要兼容 字母参数
  const bottom = integerMultiply(previousFactor_bottom, nextFactor_bottom)
  const top = integerSubtraction(integerMultiply(previousFactor_top, nextFactor_bottom), integerMultiply(nextFactor_top, previousFactor_bottom))
  // 获取分子与分母的最大公因数
  const commonFactor = getHighestCommonFactor(top, bottom)
  // 化简分子与分母
  const num_top = reduceFraction(top, commonFactor)
  const num_bottom = reduceFraction(bottom, commonFactor)
  const result = num_bottom !== '1' ? `${num_top}/${num_bottom}` : `${num_top}`

  return result
}

/**
 * @function 求乘积 - 计算因子相乘
 * @param {string} previousFactor 前一个乘数因子
 * @param {string} nextFactor 后一个乘数因子
 * @param {string} invertedPosition 因子倒置的位置，不传则默认不倒置，previous：第一个；next：第二个；
*/
export const calculateFactor_multiply = (previousFactor: string, nextFactor: string, invertedPosition?: string): string => {
  let newPreviousFactor = previousFactor
  let newNextFactor = nextFactor
  if (invertedPosition === 'previous') {
    newPreviousFactor = invertFractionTopAndBottom(previousFactor)
  }
  if (invertedPosition === 'next') {
    newNextFactor = invertFractionTopAndBottom(nextFactor)
  }
  // 拆分分子与分母
  const previousFactor_top = getFractionTopOrBottom(newPreviousFactor, 'top', false)
  const previousFactor_bottom = getFractionTopOrBottom(newPreviousFactor, 'bottom', false)
  const nextFactor_top = getFractionTopOrBottom(newNextFactor, 'top', false)
  const nextFactor_bottom = getFractionTopOrBottom(newNextFactor, 'bottom', false)
  // 计算需要兼容 字母参数
  const top = integerMultiply(previousFactor_top, nextFactor_top)
  const bottom = integerMultiply(previousFactor_bottom, nextFactor_bottom)
  // 获取分子与分母的最大公因数
  const commonFactor = getHighestCommonFactor(top, bottom)
  
  // 化简分子与分母
  const num_top = reduceFraction(top, commonFactor)
  const num_bottom = reduceFraction(bottom, commonFactor) 
  const result = num_bottom !== '1' ? `${num_top}/${num_bottom}` : `${num_top}`
  return result
}

/**
 * @function 获取分数的分子、分母
 * @param {string} fractionString 分数字符串
 * @param {string} type 获取分子传top，获取分母传bottom
 * @param {boolean} hideBracket 隐藏括号
*/
export const getFractionTopOrBottom = (fractionString: string, type: string = 'top', hideBracket: boolean = true): string => {
  if (fractionString.includes('/')) {
    // 带分母的分数
    const parts = fractionString.split('/');
    return type === 'top' ? (hideBracket ? parts[0].replace(/\(|\)/g, '') : parts[0]) : (hideBracket ? parts[1].replace(/\(|\)/g, '') : parts[1])
  } else { 
    return type === 'top' ? (hideBracket ? fractionString.replace(/\(|\)/g, '') : fractionString) : '1'
  }
}

/**
 * @function 获取最大公因数 - 辗转相除法
 * @param {string} previousStr 前一个因子
 * @param {string} nextStr 后一个因子
 * @attention 辗转相除法,入参均是整数或字母
*/
export const getHighestCommonFactor = (previousStr: string, nextStr: string): string => {
  if (stringContainChars(previousStr) || stringContainChars(nextStr)) { // 因子存在字母常数
    // 判断会否存在 “+” 或 “-” 连接 previousStr 或 nextStr
    if (!stringContainPlusOrMinus(previousStr) && !stringContainPlusOrMinus(nextStr)) { // 2个入参均不存在
      // 提取数字 - 如果返回的是undefined，默认为1
      const previousNum = getNumberOrCharFromString(previousStr, 'number') ?? '1'
      const nextNum = getNumberOrCharFromString(nextStr, 'number') ?? '1'
      // 提取字母常数 - 如果返回的是undefined，默认为空字符
      const previousChar = getNumberOrCharFromString(previousStr, 'string') ?? ''
      const nextChar = getNumberOrCharFromString(nextStr, 'string') ?? ''
      // 字母公约数
      const commonCharsFactor = getHighestCommonCharsFactor(previousChar as string, nextChar as string)
      if (nextNum === '0') return `${previousNum}${commonCharsFactor}`
      return getHighestCommonFactor(`${nextNum}${commonCharsFactor}`, `${Number(previousNum) % Number(nextNum)}${commonCharsFactor}`)
    } else { // 至少一个参数中存在 “+” 或 “-” 连接符
      
      return '9'
    }
  } else {
    // 参数均为纯数字
    if (nextStr === '0') return previousStr
    return getHighestCommonFactor(nextStr, `${Number(previousStr) % Number(nextStr)}`)
  }
}

/**
 * @function 获取字母公因数
 * @param {string} previousStr 前一个字符串
 * @param {string} nextStr 后一个字符串
 * @return {string} 相同的字母，相同的仅提取一次
 * @attention 全部参数均为字母
*/
export const getHighestCommonCharsFactor = (previousStr: string, nextStr: string): string => {
  let result = ''
  // 判断会否存在 “+” 或 “-” 连接 previousStr 或 nextStr
  if (!stringContainPlusOrMinus(previousStr) && !stringContainPlusOrMinus(nextStr)) { // 2个入参均不存在
    const previousChars = previousStr.split('')
    let nextChars = nextStr.split('') // 将nextStr转换为字符数组
    for (let i = 0; i < previousChars.length; i++) {
      let char = previousChars[i]
      let index = nextChars.indexOf(char); // 查找char在nextChars中的索引
      if (index !== -1) {
        // 如果找到了，移除nextChars中的第一个匹配字符
        nextChars.splice(index, 1);
        result += char
      }
    }
  } else { // 至少一个参数中存在 “+” 或 “-” 连接符

    return 'getHighestCommonCharsFactor'
  }
  return result
}

/**
 * @function 整数求和 - 计算整数求和
 * @param {string} previousStr 前一个整数
 * @param {string} nextStr 后一个整数
 * @attention 入参为{ 数字 + 字母 }的形式
*/
const integerAddition = (previousStr: string, nextStr: string): string => {
  if (stringContainChars(previousStr) || stringContainChars(nextStr)) { // 因子存在字母常数
    // 判断会否存在 “+” 或 “-” 连接 previousStr 或 nextStr
    if (!stringContainPlusOrMinus(previousStr) && !stringContainPlusOrMinus(nextStr)) { // 2个入参均不存在
      // 提取数字 - 如果返回的是undefined，默认为1
      const previousNum = getNumberOrCharFromString(previousStr, 'number') ?? '1'
      const nextNum = getNumberOrCharFromString(nextStr, 'number') ?? '1'
      // 提取字母常数 - 如果返回的是undefined，默认为空字符
      const previousChar = getNumberOrCharFromString(previousStr, 'string') ?? ''
      const nextChar = getNumberOrCharFromString(nextStr, 'string') ?? ''
      if (previousChar === nextChar) {
        return `${Number(previousNum) + Number(nextNum)}${previousChar}`
      } else {
        return `${previousStr}+${nextStr}`
      }
    } else { // 至少一个参数中存在 “+” 或 “-” 连接符
      
      return 'integerAddition'
    }
  } else {
    // 参数均为纯数字
    return `${Number(previousStr) + Number(nextStr)}`
  }
}

/**
 * @function 整数求差 - 计算整数求和
 * @param {string} previousStr 被减整数
 * @param {string} nextStr 减整数
 * @attention 入参为{ 数字 + 字母 }的形式
*/
const integerSubtraction = (previousStr: string, nextStr: string): string => {
  if (stringContainChars(previousStr) || stringContainChars(nextStr)) { // 因子存在字母常数
    // 判断会否存在 “+” 或 “-” 连接 previousStr 或 nextStr
    if (!stringContainPlusOrMinus(previousStr) && !stringContainPlusOrMinus(nextStr)) { // 2个入参均不存在
      return `${previousStr}-${nextStr}`
    } else { // 至少一个参数中存在 “+” 或 “-” 连接符

      return 'integerSubtraction'
    }
  } else {
    // 参数均为纯数字
    return `${Number(previousStr) - Number(nextStr)}`
  }
}

/**
 * @function 整数求乘积 - 计算整数相乘
 * @param {string} previousStr 前一个整数
 * @param {string} nextStr 后一个整数
*/
export const integerMultiply = (previousStr: string, nextStr: string): string => {
  if (previousStr === '0' || nextStr === '0') {
    return '0'
  } else if (stringContainChars(previousStr) || stringContainChars(nextStr)) { // 求积整数存在字母常数
    // 判断会否存在 “+” 或 “-” 连接 previousStr 或 nextStr
    if (!stringContainPlusOrMinus(previousStr) && !stringContainPlusOrMinus(nextStr)) { // 2个入参均不存在
      // 提取数字 - 如果返回的是undefined，默认为1
      const previousNum = getNumberOrCharFromString(previousStr, 'number') ?? '1'
      const nextNum = getNumberOrCharFromString(nextStr, 'number') ?? '1'
      // 提取字母常数 - 如果返回的是undefined，默认为空字符
      const previousChar = getNumberOrCharFromString(previousStr, 'string') ?? ''
      const nextChar = getNumberOrCharFromString(nextStr, 'string') ?? ''
      // 这里可以将字母按字母表排序一下，目前暂未排序
      return `${(Number(previousNum) * Number(nextNum) !== 1 ? Number(previousNum) * Number(nextNum) : '' )}${previousChar}${nextChar}`
    } else { // 至少一个参数中存在 “+” 或 “-” 连接符

      return 'integerMultiply'
    }
  } else {
    return `${Number(previousStr) * Number(nextStr)}`
  }
}

/**
 * @function 约分 - 计算整数相除
 * @param {string} previousStr 被除数
 * @param {string} nextStr 除数
 * @attention 入参为{ 数字 + 字母 }的形式，且{previousStr的公因数集} ⊇ {nextStr的公因数集}
*/
export const reduceFraction = (previousStr: string, nextStr: string): string => {
  if (stringContainChars(previousStr) || stringContainChars(nextStr)) { // 求积整数存在字母常数
    // 判断会否存在 “+” 或 “-” 连接 previousStr 或 nextStr
    if (!stringContainPlusOrMinus(previousStr) && !stringContainPlusOrMinus(nextStr)) { // 2个入参均不存在
      // 提取数字 - 如果返回的是undefined，默认为1
      const previousNum = getNumberOrCharFromString(previousStr, 'number') ?? '1'
      const nextNum = getNumberOrCharFromString(nextStr, 'number') ?? '1'
      // 提取字母常数 - 如果返回的是undefined，默认为空字符
      const previousChar = reduceNumCharsFraction((getNumberOrCharFromString(previousStr, 'string') ?? '') as string, (getNumberOrCharFromString(nextStr, 'string') ?? '') as string)
      // 这里可以将字母按字母表排序一下，目前暂未排序 - 字母约分待完善
      return Number(previousNum) / Number(nextNum) !== 1 ? `${Number(previousNum) / Number(nextNum)}${previousChar}`  : `${previousChar !== '' ? previousChar : '1'}`
    } else { // 至少一个参数中存在 “+” 或 “-” 连接符

      return 'reduceFraction'
    }
  } else {
    return `${Number(previousStr) / Number(nextStr)}`
  }
}